package com.yitiao.base;

import lombok.SneakyThrows;
import org.jfree.ui.RefineryUtilities;

import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 * <h3>600 个人站一排，每次随机杀掉一个奇数位的人，几号最安全？</h3>
 * <p>最安全参考两种定义方式:
 * 杀死需要的次数的期望值最大;
 * 成为最后一个被杀死的概率最大。</p>
 */
public class RandomKill {

    static Map<Integer, Integer> res = new HashMap<>();

    @SneakyThrows
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    randomKillOnce(30);
                }
                countDownLatch.countDown();
            }).start();
        }

        countDownLatch.await();
        Map.Entry<Integer, Integer> entry = res.entrySet()
                .stream()
                .max(Comparator.comparing(Map.Entry::getValue))
                .get();
        System.out.println(res);
        System.out.println("The Most Survived:[" + entry.getKey() + "]");
        System.out.println("Survived the most times:[" + entry.getValue() + "]");

        //程序执行从构造方法开始
        TestWord demo=new TestWord("曲线示例",res);
        //下面这些是弹框展示用的
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }

    private static void randomKillOnce(int people) {
        List<Integer> peopleList = new ArrayList(people);

        // 初始化600个人
        for (int i = 0; i < people; i++) {
            peopleList.add(i + 1);
        }
        // 杀599次，留一人存活
        for (int i = 0; i < people-1; i++) {
            int number = generateRandomOddNumber(0, peopleList.size());
            peopleList.remove(number - 1);
        }
        Integer alive = peopleList.get(0);
        res.put(alive, res.getOrDefault(alive, 0) + 1);
    }

    // 生成指定范围内的随机奇数
    public static int generateRandomOddNumber(int min, int max) {
        Random rand = new Random();
        int range = max - min + 1;
        int num = rand.nextInt(range / 2) * 2 + min;
        if (num % 2 == 0) {
            num += 1;
        }
        return num;
    }
}
